package com.smartleanx.module.hrm.service.payrollapproverecord;

import com.smartleanx.framework.common.pojo.PageResult;
import com.smartleanx.framework.common.util.collection.CollectionUtils;
import com.smartleanx.framework.customfield.core.service.bo.inner.CustomFieldDataBaseBO;
import com.smartleanx.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import com.smartleanx.module.hrm.controller.admin.payrollapproverecord.vo.PayrollApproveRecordPageReqVO;
import com.smartleanx.module.hrm.dal.dataobject.payrollapproverecord.PayrollApproveRecordDO;
import com.smartleanx.module.hrm.dal.dataobject.payrollapproverecord.PayrollApproveRecordDetailDO;
import com.smartleanx.module.hrm.dal.mysql.payrollapproverecord.PayrollApproveRecordMapper;
import com.smartleanx.module.hrm.eums.employee.ProcessDefinitionEnum;
import com.smartleanx.module.hrm.intergration.AdminUserServiceProvider;
import com.smartleanx.module.hrm.intergration.BpmServiceProvider;
import com.smartleanx.module.hrm.service.payroll.PayrollDetailService;
import com.smartleanx.module.hrm.service.payrollapproverecord.bo.PayrollApproveRecordDetailSaveBO;
import com.smartleanx.module.system.api.user.dto.AdminUserRespDTO;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.Collections;
import java.util.Objects;

import static com.smartleanx.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.smartleanx.module.hrm.enums.ErrorCodeConstants.*;

/**
 * 薪资审批记录 Service 实现类
 *
 * @author zhangchp
 */
@Service
@Validated
public class PayrollApproveRecordServiceImpl implements PayrollApproveRecordService {

    @Resource
    private PayrollApproveRecordMapper payrollApproveRecordMapper;

    @Resource
    private PayrollApproveRecordDetailService payrollApproveRecordDetailService;

    @Resource
    private BpmServiceProvider bpmServiceProvider;

    @Lazy
    @Resource
    private PayrollDetailService payrollDetailService;

    @Resource
    private AdminUserServiceProvider adminUserServiceProvider;

    @Override
    @Transactional(rollbackFor = Exception.class) // 添加事务，异常则回滚所有导入
    public void createRecord(Collection<PayrollApproveRecordDetailSaveBO> recordDetailSaveBOs, Collection<CustomFieldDataBaseBO> fieldDataList, Long payrollId) {
        // 插入
        PayrollApproveRecordDO record = PayrollApproveRecordDO.builder().payrollId(payrollId).build();
        AdminUserRespDTO loginUser = adminUserServiceProvider.getLoginUser();
        if(Objects.isNull(loginUser.getDeptId())){
            throw exception(PAYROLL_APPROVE_RECORD_USER_DEPT_ID_NULL);
        }
        record.setUserId(loginUser.getId());
        record.setDeptId(loginUser.getDeptId());
        payrollApproveRecordMapper.insert(record);
        recordDetailSaveBOs.forEach(saveBO -> saveBO.setPayrollApproveRecordId(record.getId()));
        payrollApproveRecordDetailService.createDetail(recordDetailSaveBOs, fieldDataList);
        // 审批相关
        // 发起 BPM 流程
        String processInstanceId = bpmServiceProvider.createProcessInstance(
                new BpmProcessInstanceCreateReqDTO()
                        .setProcessDefinitionKey(ProcessDefinitionEnum.PAYROLL_APPROVE.getKey())
                        .setVariables(Collections.emptyMap())
                        .setBusinessKey(record.getId().toString())
        );
        payrollApproveRecordMapper.updateProcessInstanceId(processInstanceId, record.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class) // 添加事务，异常则回滚所有导入
    public void updateApproveResult(Long id, Integer approveResult) {
        // 校验存在
        validateRecordExists(id);
        // 更新
        payrollApproveRecordMapper.updateApproveResult(approveResult, id);
        payrollDetailService.updateApproveResult(CollectionUtils.convertList(payrollApproveRecordDetailService.getDetailByPayrollApproveRecordId(id),
                PayrollApproveRecordDetailDO::getPayrollDetailId), approveResult);
    }

    private void validateRecordExists(Long id) {
        if (payrollApproveRecordMapper.selectById(id) == null) {
            throw exception(PAYROLL_APPROVE_RECORD_NOT_EXISTS);
        }
    }

    @Override
    public PayrollApproveRecordDO getRecord(Long id) {
        return payrollApproveRecordMapper.selectById(id);
    }

    @Override
    public PageResult<PayrollApproveRecordDO> getRecordPage(PayrollApproveRecordPageReqVO pageReqVO) {
        return payrollApproveRecordMapper.selectPage(pageReqVO);
    }

}